package showtime.framework.engine
{
	/**
	 * Cache.as
	 * Yin Hao
	 * @version 1.0.0
	 * 
	 * Description.
	 * 
	 * Copyright (c) 2012 Yin Hao
	 * 
	 * Permission is hereby granted, free of charge, to any person obtaining a copy
	 * of this software and associated documentation files (the "Software"), to deal
	 * in the Software without restriction, including without limitation the rights
	 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	 * copies of the Software, and to permit persons to whom the Software is
	 * furnished to do so, subject to the following conditions:
	 * 
	 * The above copyright notice and this permission notice shall be included in
	 * all copies or substantial portions of the Software.
	 * 
	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	 * THE SOFTWARE.
	 */
	
	import flash.display.BitmapData;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import showtime.framework.engine.animation.AnimationFrame;

	public final class Cache
	{
		static public var cache:Object = null;
		
		{	
			cache = {};
		}
		
		/**
		 * Check Bitmap cache. 
		 * @param key
		 * @return 
		 * 
		 */		
		static public function checkBitmapCache(key:String):Boolean
		{
			return (cache[key] != undefined) && (cache[key] != null);
		}

		static public function clearCache():void
		{
			var pixels:BitmapData = null;
			
			for (var key:* in cache)
			{
				pixels = cache[key];
				pixels.dispose();
				pixels = null;
				
				delete cache[key];
			}
		}
		
		static public function createBitmap(key:String, graphicWidth:int, graphicHeight:int, color:uint):BitmapData
		{
			if (key == null)
			{
				key = graphicWidth + "x" + graphicHeight + ":" + color;
			}
			
			if (!checkBitmapCache(key))
			{
				cache[key] = new BitmapData(graphicWidth, graphicHeight, true, color);
			}
			
			return cache[key];
		}
		
		/**
		 *
		 *  
		 * @param key
		 * @param graphic
		 * @param frameConfigs
		 * @param reverse
		 * @return 
		 * 
		 */		
		static public function addBitmapFrames(key:String, graphic:BitmapData, frameConfigs:Array, reverse:Boolean):Array
		{						
			if (!checkBitmapCache(key))
			{
				var frames:Array = [];
				
				var reverseGraphic:BitmapData = null;
				
				if (reverse)
				{		
					reverseGraphic = new BitmapData(graphic.width, graphic.height, true, 0x00000000);					
					
					var mtx:Matrix = new Matrix();
					mtx.scale(-1, 1);
					
					mtx.translate(reverseGraphic.width, 0);
					reverseGraphic.draw(graphic, mtx);
				}
				
				for each (var frameConfig:AnimationFrame in frameConfigs)
				{
					var bmp:BitmapData = new BitmapData(frameConfig.width, frameConfig.height, true);
					
					if(frameConfig.reversed)
					{
						bmp.copyPixels(reverseGraphic, new Rectangle(frameConfig.dx, frameConfig.dy, frameConfig.width, frameConfig.height), new Point());
					}					
					else
					{
						bmp.copyPixels(graphic, new Rectangle(frameConfig.dx, frameConfig.dy, frameConfig.width, frameConfig.height), new Point());
					}				
					
					frames.push(bmp);
				}
				
				cache[key] = frames;
			}	
			
			return cache[key];
			
		}
		/**
		 *  
		 * @param graphic
		 * @param reverse
		 * @param unique
		 * @param key
		 * @return 
		 * 
		 */		
		static public function addBitmap(key:String, graphic:BitmapData, reverse:Boolean = false):BitmapData
		{
			if (key == null)
			{
				key = String(graphic);
			}
			
			// Not exist.
			if (!checkBitmapCache(key))
			{
				if (reverse)
				{
					var newPixels:BitmapData = new BitmapData(graphic.width << 1, graphic.height, true, 0x00000000);
					newPixels.draw(graphic);
					
					var mtx:Matrix = new Matrix();				
					mtx.scale(-1, 1);
					
					mtx.translate(newPixels.width, 0);
					newPixels.draw(graphic, mtx);
					
					graphic = newPixels;
				}				
				
				cache[key] = graphic;
			}			
			
			return cache[key];
			
		}
	}
}